// check main pointer
owl_bool owl_check_smg_ank1_main_pointer(owl_byte * src, owl_umax size)
{
  return (src != NULL && size >= sizeof(owl_smg_ank1_main));
}

// check ext pointer
owl_bool owl_check_smg_ank1_ext_pointer(owl_byte * src, owl_umax size)
{
  return (src != NULL && size >= sizeof(owl_smg_ank1_extra));
}

// check pointer
owl_bool owl_check_smg_ank1_pointer(owl_byte * src, owl_umax size)
{
  return (src != NULL && size >= sizeof(owl_smg_ank1));
}

// check main
owl_bool owl_check_smg_ank1_main_members(owl_byte loop_mode,
                                         owl_byte rot_lshift,
                                         owl_umax anim_length,
                                         owl_umax bone_count,
                                         owl_umax scale_arr_length,
                                         owl_umax rot_arr_length,
                                         owl_umax transl_arr_length,
                                         struct owl_smg_ank1_bone_anim_data ** bone_anim_data,
                                         owl_fmax * scale_arr,
                                         owl_smax * rot_arr,
                                         owl_fmax * transl_arr)
{
  // check params
  if (loop_mode > 4 || bone_count == 0 || scale_arr_length == 0 || rot_arr_length == 0 || transl_arr_length == 0
      || bone_anim_data == NULL || scale_arr == NULL || rot_arr == NULL || transl_arr == NULL)
    goto err;
  
  // check bone_anim_data
  for (owl_umax i = 0; i < bone_count; i++)
    for (owl_umax j = 0; j < OWL_SMG_ANK1_COMP_LENGTH; j++) {
      // get the length of the current array
      owl_umax arr_length = scale_arr_length;
      if (j == OWL_SMG_ANK1_X_ROT_POS
          || j == OWL_SMG_ANK1_Y_ROT_POS
          || j == OWL_SMG_ANK1_Z_ROT_POS)
        arr_length = rot_arr_length;
      else if (j == OWL_SMG_ANK1_X_TRANSL_POS
               || j == OWL_SMG_ANK1_Y_TRANSL_POS
               || j == OWL_SMG_ANK1_Z_TRANSL_POS)
        arr_length = transl_arr_length;
      
      // number of keyframes can be anything just check agaisnt the respective array size for overflow
      if (bone_anim_data[i][j].kf_count <= 1) {
        // keyframe only contains a single value
        if (bone_anim_data[i][j].data_index + 1 > arr_length)
          goto err;
      } else {
        // keyframe contains 3 values
        if (bone_anim_data[i][j].interp_mode == OWL_SMG_ANK1_INTERP_SOFT) {
          // check index and size
          if (bone_anim_data[i][j].data_index + (3 * (bone_anim_data[i][j].kf_count)) > arr_length)
            goto err;        
        } // keyframe contains 4 values
        else if (bone_anim_data[i][j].interp_mode == OWL_SMG_ANK1_INTERP_CUSTOM) {
          // check index and size
          if (bone_anim_data[i][j].data_index + (4 * (bone_anim_data[i][j].kf_count)) > arr_length)
            goto err;
        }
      }
    }
  
  // raw check the float arrays for faulty floats first
  for (owl_umax i = 0; i < scale_arr_length; i++)
    if (owl_check_float(scale_arr[i]) == owl_false)
      goto err;
  for (owl_umax i = 0; i < transl_arr_length; i++)
    if (owl_check_float(transl_arr[i]) == owl_false)
      goto err;
  
  // by going through bone_anim_data, check scale_arr, rot_arr and transl_arr
  // to check for keyframe logic (timing must be ascending - weird shit happens
  // when this does not happen but I cannot understand yet how to predict it)
  for (owl_umax i = 0; i < OWL_SMG_ANK1_COMP_LENGTH; i++)
    for (owl_umax j = 0; j < bone_count; j++)
    {
      // get the array to be processed
      owl_fmax * farr = scale_arr;
      owl_smax * sarr = rot_arr;
      if (i == OWL_SMG_ANK1_X_TRANSL_POS || i == OWL_SMG_ANK1_Y_TRANSL_POS || i == OWL_SMG_ANK1_Z_TRANSL_POS)
        farr = transl_arr;
      
      // get the number of values to be read per keyframe
      owl_byte num_values = 0;
      if (bone_anim_data[j][i].kf_count > 1)
      {
        if (bone_anim_data[j][i].interp_mode == OWL_SMG_ANK1_INTERP_SOFT)
          num_values = 3;
        else if (bone_anim_data[j][i].interp_mode == OWL_SMG_ANK1_INTERP_CUSTOM)
          num_values = 4;
      } else 
        continue; // skip the single values
      
      // read the respective section of the array
      if (i == OWL_SMG_ANK1_X_SCALE_POS || i == OWL_SMG_ANK1_Y_SCALE_POS || i == OWL_SMG_ANK1_Z_SCALE_POS
          || i == OWL_SMG_ANK1_X_TRANSL_POS || i == OWL_SMG_ANK1_Y_TRANSL_POS || i == OWL_SMG_ANK1_Z_TRANSL_POS)
      { // scale_arr or transl_arr
        for (owl_umax k = 0, index = bone_anim_data[j][i].data_index;
             k < bone_anim_data[j][i].kf_count;
             k++, index += num_values)
          // time on current keyframe cannot be less or equal to the time on the previous keyframe
          if (k != 0 && farr[index] <= farr[index - num_values]) goto err;
      }
      else
      { // rot_arr
        for (owl_umax k = 0, index = bone_anim_data[j][i].data_index;
             k < bone_anim_data[j][i].kf_count;
             k++, index += num_values)
          // time on current keyframe cannot be less or equal to the time on the previous keyframe
          if (k != 0 && sarr[index] <= sarr[index - num_values]) goto err;
      }
    }
  
  // done!
  return owl_true;
  err:
  return owl_false;
}

// check main all
owl_bool owl_check_smg_ank1_main_all(owl_smg_ank1_main * main, owl_umax size)
{
  return (owl_check_smg_ank1_main_pointer((void *) main, size) == owl_true
          && owl_check_smg_ank1_main_members(main -> loop_mode,
                                             main -> rot_lshift,
                                             main -> anim_length,
                                             main -> bone_count,
                                             main -> scale_arr_length,
                                             main -> rot_arr_length,
                                             main -> transl_arr_length,
                                             main -> bone_anim_data,
                                             main -> scale_arr,
                                             main -> rot_arr,
                                             main -> transl_arr) == owl_true);
}

// check all
owl_bool owl_check_smg_ank1_all(owl_smg_ank1 * ank1, owl_umax size)
{
  // check params
  if (ank1 == NULL
      || size < sizeof(owl_smg_ank1)
      || owl_check_smg_ank1_main_all(ank1 -> main, sizeof(owl_smg_ank1_main)) == owl_false)
    goto err;
  if (ank1 -> ext == NULL) // this structure section is not strictly required
    return owl_true;
  
  // check all data together
  
  // variables to ease the check
  owl_umax tmp1 = 0, tmp2 = 0;
  
  // magic
  if (ank1 -> ext -> magic != OWL_SMG_ANK1_MAGIC[0][0]
      && ank1 -> ext -> magic != OWL_SMG_ANK1_MAGIC[0][1]) goto err;
  // bone_anim_data_offset
  if (ank1 -> ext -> bone_anim_data_offset != OWL_SMG_ANK1_BONE_ANIM_DATA_OFFSET) goto err;
  // pad1_size
  if (ank1 -> ext -> pad1_size != OWL_SMG_ANK1_PAD1_SIZE) goto err;
  tmp1 += OWL_SMG_ANK1_BONE_ANIM_DATA_OFFSET + (ank1 -> main -> bone_count * OWL_SMG_ANK1_COMP_LENGTH * 6);
  tmp1 += (tmp2 = owl_get_padding_align_32_length(tmp1));
  // scale_arr_offset
  if (ank1 -> ext -> scale_arr_offset != tmp1) goto err;
  // pad2_size
  if (ank1 -> ext -> pad2_size != tmp2) goto err;
  tmp1 += ank1 -> main -> scale_arr_length * 4;
  tmp1 += (tmp2 = owl_get_padding_align_32_length(tmp1));
  // rot_arr_offset
  if (ank1 -> ext -> rot_arr_offset != tmp1) goto err;
  // pad3_size
  if (ank1 -> ext -> pad3_size != tmp2) goto err;
  tmp1 += ank1 -> main -> rot_arr_length * 2;
  tmp1 += (tmp2 = owl_get_padding_align_32_length(tmp1));
  // transl_arr_offset
  if (ank1 -> ext -> transl_arr_offset != tmp1) goto err;
  // pad4_size
  if (ank1 -> ext -> pad4_size != tmp2) goto err;
  tmp1 += ank1 -> main -> transl_arr_length * 4;
  tmp1 += (tmp2 = owl_get_padding_align_32_length(tmp1));
  // size
  if (ank1 -> ext -> size != tmp1) goto err;
  // pad5_size
  if (ank1 -> ext -> pad5_size != tmp2) goto err;
  
  // done!
  return owl_true;
  err:
  return owl_false;
}

// create
owl_smg_ank1 * owl_create_smg_ank1(owl_str * raw, owl_endian endian)
{
  // check params
  owl_smg_ank1 * new = NULL;
  owl_mem_space * tmp_sp = NULL;
  OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_ALL_GOOD;
  OWL_SMG_ANK1_ERR_READ_POS = 0;
  if (owl_check_str_all(raw, sizeof(owl_str)) == owl_false
      || owl_check_endian(endian) == owl_false)
    {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_FUNC_PARAMS; goto err;}
  
  // fill new while checking it
  tmp_sp = owl_create_mem_space(sizeof(owl_smg_ank1));
  if (tmp_sp == NULL) {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_MEM_ALLOC; goto err;}
  new = (void *) tmp_sp -> ptr;
  tmp_sp = owl_create_mem_space(sizeof(owl_smg_ank1_main));
  if (tmp_sp == NULL) {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_MEM_ALLOC; goto err;}
  new -> main = (void *) tmp_sp -> ptr;
  tmp_sp = owl_create_mem_space(sizeof(owl_smg_ank1_extra));
  if (tmp_sp == NULL) {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_MEM_ALLOC; goto err;}
  new -> ext = (void *) tmp_sp -> ptr;
  
  // variables to help read raw
  owl_bitarr bits = {&((owl_mem_space) {raw -> arr -> ptr, raw -> arr -> size}), 0, 0};
  owl_umax tmp1 = 0, tmp2 = 0;
  
  // section header magic and size and endian detection
  if (bits.arr -> size < 8) {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_STR_SIZE; goto err;}
  new -> ext -> magic = owl_get_std_uint32_mw(&bits, OWL_ENDIAN_BIG).integer.u;
  if (new -> ext -> magic != OWL_SMG_ANK1_MAGIC[0][endian == OWL_ENDIAN_BIG ? 0 : 1])
    {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_MAGIC_1; goto err;}
  new -> ext -> size = owl_get_std_uint32_mw(&bits, endian).integer.u;
  if (new -> ext -> size % 32 != 0 || new -> ext -> size == 0 || new -> ext -> size > raw -> arr -> size)
    {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_SIZE_1; goto err;}
  bits.arr -> size = new -> ext -> size - 8; // assign the new size and keep the check with that

  // loop_mode, rot_lshift, anim_length, bone_count, scale_arr_length, rot_arr_length and transl_arr_length
  if (bits.arr -> size < 12) {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_STR_SIZE; goto err;}
  new -> main -> loop_mode = owl_get_std_uint8_mw(&bits, endian).integer.u;
  if (new -> main -> loop_mode > 4) {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_LOOP_MODE_1; goto err;}
  new -> main -> rot_lshift = owl_get_std_uint8_mw(&bits, endian).integer.u;
  new -> main -> anim_length = owl_get_std_uint16_mw(&bits, endian).integer.u;
  new -> main -> bone_count = owl_get_std_uint16_mw(&bits, endian).integer.u;
  new -> main -> scale_arr_length = owl_get_std_uint16_mw(&bits, endian).integer.u;
  new -> main -> rot_arr_length = owl_get_std_uint16_mw(&bits, endian).integer.u;
  new -> main -> transl_arr_length = owl_get_std_uint16_mw(&bits, endian).integer.u;
  
  // bone_anim_data_offset, scale_arr_offset, rot_arr_offset and transl_arr_offset
  // also the 5 padding sizes and the section size
  if (bits.arr -> size < 16) {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_STR_SIZE; goto err;}
  new -> ext -> bone_anim_data_offset = owl_get_std_uint32_mw(&bits, endian).integer.u;
  if (new -> ext -> bone_anim_data_offset != OWL_SMG_ANK1_BONE_ANIM_DATA_OFFSET)
    {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_BONE_ANIM_DATA_OFFSET_1; goto err;}
  new -> ext -> pad1_size = OWL_SMG_ANK1_PAD1_SIZE;
  tmp1 = OWL_SMG_ANK1_BONE_ANIM_DATA_OFFSET + (new -> main -> bone_count * OWL_SMG_ANK1_COMP_LENGTH * 6);
  tmp1 += (tmp2 = owl_get_padding_align_32_length(tmp1));
  new -> ext -> scale_arr_offset = owl_get_std_uint32_mw(&bits, endian).integer.u;
  if (new -> ext -> scale_arr_offset != tmp1)
    {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_SCALE_ARR_OFFSET_1; goto err;}
  new -> ext -> pad2_size = tmp2;
  tmp1 += new -> main -> scale_arr_length * 4;
  tmp1 += (tmp2 = owl_get_padding_align_32_length(tmp1));
  new -> ext -> rot_arr_offset = owl_get_std_uint32_mw(&bits, endian).integer.u;
  if (new -> ext -> rot_arr_offset != tmp1)
    {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_ROT_ARR_OFFSET_1; goto err;}
  new -> ext -> pad3_size = tmp2;
  tmp1 += new -> main -> rot_arr_length * 2;
  tmp1 += (tmp2 = owl_get_padding_align_32_length(tmp1));
  new -> ext -> transl_arr_offset = owl_get_std_uint32_mw(&bits, endian).integer.u;
  if (new -> ext -> transl_arr_offset != tmp1)
    {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_TRANSL_ARR_OFFSET_1; goto err;}
  new -> ext -> pad4_size = tmp2;
  tmp1 += new -> main -> transl_arr_length * 4;
  tmp1 += (tmp2 = owl_get_padding_align_32_length(tmp1));
  if (new -> ext -> size != tmp1) {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_SIZE_1; goto err;}
  new -> ext -> pad5_size = tmp2;
  
  // pad1
  if (bits.arr -> size < OWL_SMG_ANK1_PAD1_SIZE) {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_STR_SIZE; goto err;}
  bits.arr -> ptr += OWL_SMG_ANK1_PAD1_SIZE;
  bits.arr -> size -= OWL_SMG_ANK1_PAD1_SIZE;
  
  // bone_anim_data
  if (bits.arr -> size < (new -> main -> bone_count * OWL_SMG_ANK1_COMP_LENGTH * 6))
    {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_STR_SIZE; goto err;}
  // allocate space for the structs
  tmp_sp = owl_create_mem_space(sizeof(struct owl_smg_ank1_bone_anim_data *) * new -> main -> bone_count);
  if (tmp_sp == NULL) {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_MEM_ALLOC; goto err;}
  new -> main -> bone_anim_data = (void *) tmp_sp -> ptr;
  for (owl_umax i = 0; i < new -> main -> bone_count; i++) {
    tmp_sp = owl_create_mem_space(sizeof(struct owl_smg_ank1_bone_anim_data) * OWL_SMG_ANK1_COMP_LENGTH);
    if (tmp_sp == NULL) {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_MEM_ALLOC; goto err;}
    (new -> main -> bone_anim_data)[i] = (void *) tmp_sp -> ptr;
  }
  // fill the structs with data (almost a copy/paste from check_all)
  for (owl_umax i = 0; i < new -> main -> bone_count; i++)
    for (owl_umax j = 0; j < OWL_SMG_ANK1_COMP_LENGTH; j++) {
      // determine the array to be working with
      // get the length of the current array
      owl_umax arr_length = new -> main -> scale_arr_length;
      if (j == OWL_SMG_ANK1_X_ROT_POS
          || j == OWL_SMG_ANK1_Y_ROT_POS
          || j == OWL_SMG_ANK1_Z_ROT_POS)
        arr_length = new -> main -> rot_arr_length;
      else if (j == OWL_SMG_ANK1_X_TRANSL_POS
               || j == OWL_SMG_ANK1_Y_TRANSL_POS
               || j == OWL_SMG_ANK1_Z_TRANSL_POS)
        arr_length = new -> main -> transl_arr_length;
      
      // grab the number of keyframes, the data index and the interpolation mode
      // then check if nothing goes out of the component array
      (new -> main -> bone_anim_data)[i][j].kf_count = owl_get_std_uint16_mw(&bits, endian).integer.u;
      (new -> main -> bone_anim_data)[i][j].data_index = owl_get_std_uint16_mw(&bits, endian).integer.u;
      (new -> main -> bone_anim_data)[i][j].interp_mode = owl_get_std_uint16_mw(&bits, endian).integer.u;
      
      // number of keyframes can be anything just check agaisnt the respective array size for overflow
      if ((new -> main -> bone_anim_data)[i][j].kf_count == 0
          || (new -> main -> bone_anim_data)[i][j].kf_count == 1) {
        // keyframe only contains a single value
        if ((new -> main -> bone_anim_data)[i][j].data_index + 1 > arr_length)
          {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_BONE_ANIM_DATA_1; goto err;}
      } else {
        // keyframe contains 3 values
        if ((new -> main -> bone_anim_data)[i][j].interp_mode == OWL_SMG_ANK1_INTERP_SOFT) {
          // check index and size
          if ((new -> main -> bone_anim_data)[i][j].data_index
              + (3 * ((new -> main -> bone_anim_data)[i][j].kf_count)) > arr_length)
            {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_BONE_ANIM_DATA_1; goto err;} 
        } // keyframe contains 4 values
        else if ((new -> main -> bone_anim_data)[i][j].interp_mode == OWL_SMG_ANK1_INTERP_CUSTOM) {
          // check index and size
          if ((new -> main -> bone_anim_data)[i][j].data_index
              + (4 * ((new -> main -> bone_anim_data)[i][j].kf_count)) > arr_length)
            {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_BONE_ANIM_DATA_1; goto err;}
        }
      }
    }
  
  // pad2
  if (bits.arr -> size < new -> ext -> pad2_size) {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_STR_SIZE; goto err;}
  bits.arr -> ptr += new -> ext -> pad2_size;
  bits.arr -> size -= new -> ext -> pad2_size;
  
  // scale_arr
  if (bits.arr -> size < new -> main -> scale_arr_length * 4)
    {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_STR_SIZE; goto err;}
  // allocate space for the struct
  tmp_sp = owl_create_mem_space(sizeof(owl_fmax) * new -> main -> scale_arr_length);
  if (tmp_sp == NULL) {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_MEM_ALLOC; goto err;}
  new -> main -> scale_arr = (void *) tmp_sp -> ptr;
  for (owl_umax i = 0; i < new -> main -> scale_arr_length; i++) {
    owl_float_op_result tmp = owl_get_std_float32_mw(&bits, endian);
    if (tmp.success == owl_false) {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_SCALE_ARR_1; goto err;}
    (new -> main -> scale_arr)[i] = tmp.f;
  }
  
  // pad3
  if (bits.arr -> size < new -> ext -> pad3_size) {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_STR_SIZE; goto err;}
  bits.arr -> ptr += new -> ext -> pad3_size;
  bits.arr -> size -= new -> ext -> pad3_size;
  
  // rot_arr
  if (bits.arr -> size < new -> main -> rot_arr_length * 2)
    {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_STR_SIZE; goto err;}
  // allocate space for the struct
  tmp_sp = owl_create_mem_space(sizeof(owl_smax) * new -> main -> rot_arr_length);
  if (tmp_sp == NULL) {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_MEM_ALLOC; goto err;}
  new -> main -> rot_arr = (void *) tmp_sp -> ptr;
  for (owl_umax i = 0; i < new -> main -> rot_arr_length; i++)
    (new -> main -> rot_arr)[i] = owl_get_std_sint16_mw(&bits, endian).integer.s;
  
  // pad4
  if (bits.arr -> size < new -> ext -> pad4_size) {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_STR_SIZE; goto err;}
  bits.arr -> ptr += new -> ext -> pad4_size;
  bits.arr -> size -= new -> ext -> pad4_size;
  
  // transl_arr
  if (bits.arr -> size < new -> main -> transl_arr_length * 4)
    {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_STR_SIZE; goto err;}
  // allocate space for the struct
  tmp_sp = owl_create_mem_space(sizeof(owl_fmax) * new -> main -> transl_arr_length);
  if (tmp_sp == NULL) {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_MEM_ALLOC; goto err;}
  new -> main -> transl_arr = (void *) tmp_sp -> ptr;
  for (owl_umax i = 0; i < new -> main -> transl_arr_length; i++) {
    owl_float_op_result tmp = owl_get_std_float32_mw(&bits, endian);
    if (tmp.success == owl_false) {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_TRANSL_ARR_1; goto err;}
    (new -> main -> transl_arr)[i] = tmp.f;
  }
  
  // pad5
  if (bits.arr -> size < new -> ext -> pad5_size) {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_STR_SIZE; goto err;}
  bits.arr -> ptr += new -> ext -> pad5_size;
  bits.arr -> size -= new -> ext -> pad5_size;

  // incredible almost last check
  if (bits.arr -> size != 0) {OWL_SMG_ANK1_ERR_CD = OWL_SMG_ANK1_ERR_STR_SIZE; goto err;}
  
  // check keyframe logic (almost a copy/paste from check_all)
  for (owl_umax i = 0; i < OWL_SMG_ANK1_COMP_LENGTH; i++)
    for (owl_umax j = 0; j < new -> main -> bone_count; j++)
    {
      // get the array to be processed
      owl_fmax * farr = new -> main -> scale_arr;
      owl_smax * sarr = new -> main -> rot_arr;
      if (i == OWL_SMG_ANK1_X_TRANSL_POS || i == OWL_SMG_ANK1_Y_TRANSL_POS || i == OWL_SMG_ANK1_Z_TRANSL_POS)
        farr = new -> main -> transl_arr;
      
      // get the number of values to be read per keyframe
      owl_byte num_values = 0;
      if ((new -> main -> bone_anim_data[j][i]).kf_count > 1)
      {
        if ((new -> main -> bone_anim_data[j][i]).interp_mode == OWL_SMG_ANK1_INTERP_SOFT)
          num_values = 3;
        else if ((new -> main -> bone_anim_data[j][i]).interp_mode == OWL_SMG_ANK1_INTERP_CUSTOM)
          num_values = 4;
      } else 
        continue; // skip the single values
      
      // read the respective section of the array
      if (i == OWL_SMG_ANK1_X_SCALE_POS || i == OWL_SMG_ANK1_Y_SCALE_POS || i == OWL_SMG_ANK1_Z_SCALE_POS
          || i == OWL_SMG_ANK1_X_TRANSL_POS || i == OWL_SMG_ANK1_Y_TRANSL_POS || i == OWL_SMG_ANK1_Z_TRANSL_POS)
      { // scale_arr or transl_arr
        for (owl_umax k = 0, index = (new -> main -> bone_anim_data[j][i]).data_index;
             k < (new -> main -> bone_anim_data[j][i]).kf_count;
             k++, index += num_values)
          // time on current keyframe cannot be less or equal to the time on the previous keyframe
          if (k != 0 && farr[index] <= farr[index - num_values]) goto err;
      }
      else
      { // rot_arr
        for (owl_umax k = 0, index = (new -> main -> bone_anim_data[j][i]).data_index;
             k < (new -> main -> bone_anim_data[j][i]).kf_count;
             k++, index += num_values)
          // time on current keyframe cannot be less or equal to the time on the previous keyframe
          if (k != 0 && sarr[index] <= sarr[index - num_values]) goto err;
      }
    }
  
  // done!
  return new;
  err: // something bad happened
  OWL_SMG_ANK1_ERR_READ_POS = bits.arr -> ptr - raw -> arr -> ptr;
  if (new != NULL) {
    if (new -> main != NULL) {
      if (new -> main -> bone_anim_data != NULL) {
        for (owl_umax i = 0; i < new -> main -> bone_count; i++)
          owl_free_mem_space(&((owl_mem_space) {(void *) (new -> main -> bone_anim_data)[i], 1}));
        owl_free_mem_space(&((owl_mem_space) {(void *) new -> main -> bone_anim_data, 1}));
      }
      owl_free_mem_space(&((owl_mem_space) {(void *) new -> main -> scale_arr, 1}));
      owl_free_mem_space(&((owl_mem_space) {(void *) new -> main -> rot_arr, 1}));
      owl_free_mem_space(&((owl_mem_space) {(void *) new -> main -> transl_arr, 1}));
      owl_free_mem_space(&((owl_mem_space) {(void *) new -> main, 1}));
    }
    owl_free_mem_space(&((owl_mem_space) {(void *) new -> ext, 1}));
    owl_free_mem_space(&((owl_mem_space) {(void *) new, 1}));
    owl_free_mem_space(tmp_sp);
  }
  return NULL;
}

// free
owl_umax owl_free_smg_ank1(owl_smg_ank1 * ank1)
{
  // check params
  if (owl_check_smg_ank1_all(ank1, sizeof(owl_smg_ank1)) == owl_false)
    goto err;
  
  // free the memory used by each structure component
  
  // main
  for (owl_umax i = 0; i < ank1 -> main -> bone_count; i++)
    owl_free_mem_space(&((owl_mem_space) {(void *) (ank1 -> main -> bone_anim_data)[i], 1}));
  owl_free_mem_space(&((owl_mem_space) {(void *) ank1 -> main -> bone_anim_data, 1}));
  owl_free_mem_space(&((owl_mem_space) {(void *) ank1 -> main -> scale_arr, 1}));
  owl_free_mem_space(&((owl_mem_space) {(void *) ank1 -> main -> rot_arr, 1}));
  owl_free_mem_space(&((owl_mem_space) {(void *) ank1 -> main -> transl_arr, 1}));
  owl_free_mem_space(&((owl_mem_space) {(void *) ank1 -> main, 1}));
  // ext
  owl_free_mem_space(&((owl_mem_space) {(void *) ank1 -> ext, 1}));
  
  // the structure itself
  return owl_free_mem_space(&((owl_mem_space) {(void *) ank1, 1}));
  err:
  return 0;
}

// print
owl_umax owl_print_smg_ank1(owl_byte * src, owl_umax size)
{
  // check params
  printf("OWL_SMG_ANK1 struct info:\n");
  printf("  Struct info: %p, %llu\n", src, size);
  if (owl_check_smg_ank1_all((void *) src, size) == owl_false)
    return 0;
  
  // else print the structure
  owl_smg_ank1 * ank1 = (void *) src;
  
  // main
  printf("  OWL_SMG_ANK1_MAIN struct info:\n");
  printf("    Struct info: %p, %lu\n", ank1 -> main, sizeof(owl_smg_ank1_main));
  printf("    Loop Mode: %u\n", ank1 -> main -> loop_mode);
  printf("    Rotation left shift: %u\n", ank1 -> main -> rot_lshift);
  printf("    Animation length (frames): %llu\n", ank1 -> main -> anim_length);
  printf("    Bone count: %llu\n", ank1 -> main -> bone_count);
  printf("    Scale array length: %llu\n", ank1 -> main -> scale_arr_length);
  printf("    Rotation array length: %llu\n", ank1 -> main -> rot_arr_length);
  printf("    Translation array length: %llu\n", ank1 -> main -> transl_arr_length);
  printf("    Bone animation data: keyframe count, data index, interpolation mode\n");
  for (owl_umax i = 0; i < ank1 -> main -> bone_count; i++) {
    printf("      Bone[%llu]: Scale/Rot/Transl XYZ\n", i);
    for (owl_umax j = 0; j < OWL_SMG_ANK1_COMP_LENGTH; j++) {
      switch (j) {
        case (OWL_SMG_ANK1_X_SCALE_POS):
          printf("        X -> S: %llu, %llu, %d | ", (ank1 -> main -> bone_anim_data)[i][j].kf_count,
                                                      (ank1 -> main -> bone_anim_data)[i][j].data_index,
                                                      (ank1 -> main -> bone_anim_data)[i][j].interp_mode);
          break;
        case (OWL_SMG_ANK1_X_ROT_POS):
          printf("R: %llu, %llu, %d | ", (ank1 -> main -> bone_anim_data)[i][j].kf_count,
                                                         (ank1 -> main -> bone_anim_data)[i][j].data_index,
                                                         (ank1 -> main -> bone_anim_data)[i][j].interp_mode);
          break;
        case (OWL_SMG_ANK1_X_TRANSL_POS):
          printf("T: %llu, %llu, %d\n", (ank1 -> main -> bone_anim_data)[i][j].kf_count,
                                                            (ank1 -> main -> bone_anim_data)[i][j].data_index,
                                                            (ank1 -> main -> bone_anim_data)[i][j].interp_mode);
          break;
        case (OWL_SMG_ANK1_Y_SCALE_POS):
          printf("        Y -> S: %llu, %llu, %d | ", (ank1 -> main -> bone_anim_data)[i][j].kf_count,
                                                      (ank1 -> main -> bone_anim_data)[i][j].data_index,
                                                      (ank1 -> main -> bone_anim_data)[i][j].interp_mode);
          break;
        case (OWL_SMG_ANK1_Y_ROT_POS):
          printf("R: %llu, %llu, %d | ", (ank1 -> main -> bone_anim_data)[i][j].kf_count,
                                                         (ank1 -> main -> bone_anim_data)[i][j].data_index,
                                                         (ank1 -> main -> bone_anim_data)[i][j].interp_mode);
          break;
        case (OWL_SMG_ANK1_Y_TRANSL_POS):
          printf("T: %llu, %llu, %d\n", (ank1 -> main -> bone_anim_data)[i][j].kf_count,
                                                            (ank1 -> main -> bone_anim_data)[i][j].data_index,
                                                            (ank1 -> main -> bone_anim_data)[i][j].interp_mode);
          break;
        case (OWL_SMG_ANK1_Z_SCALE_POS):
          printf("        Z -> S: %llu, %llu, %d | ", (ank1 -> main -> bone_anim_data)[i][j].kf_count,
                                                    (ank1 -> main -> bone_anim_data)[i][j].data_index,
                                                    (ank1 -> main -> bone_anim_data)[i][j].interp_mode);
          break;
        case (OWL_SMG_ANK1_Z_ROT_POS):
          printf("R: %llu, %llu, %d | ", (ank1 -> main -> bone_anim_data)[i][j].kf_count,
                                                         (ank1 -> main -> bone_anim_data)[i][j].data_index,
                                                         (ank1 -> main -> bone_anim_data)[i][j].interp_mode);
          break;
        case (OWL_SMG_ANK1_Z_TRANSL_POS):
          printf("T: %llu, %llu, %d\n", (ank1 -> main -> bone_anim_data)[i][j].kf_count,
                                                            (ank1 -> main -> bone_anim_data)[i][j].data_index,
                                                            (ank1 -> main -> bone_anim_data)[i][j].interp_mode);
          break;
        default: break;
      }
    }
  }
  printf("    Scale array: ");
  for (owl_umax i = 0; i < ank1 -> main -> scale_arr_length; i++)
    printf("| %.3lf ", (ank1 -> main -> scale_arr)[i]);
  printf("|\n");
  printf("    Rotation array: ");
  for (owl_umax i = 0; i < ank1 -> main -> rot_arr_length; i++)
    printf("| %lld ", (ank1 -> main -> rot_arr)[i]);
  printf("|\n");
  printf("    Translation array: ");
  for (owl_umax i = 0; i < ank1 -> main -> transl_arr_length; i++)
    printf("| %.3lf ", (ank1 -> main -> transl_arr)[i]);
  printf("|\n");
  
  // extra
  if (ank1 -> ext == NULL) goto end;
  printf("  OWL_SMG_ANK1_EXTRA struct info:\n");
  printf("    Struct info: %p, %lu\n", ank1 -> ext, sizeof(owl_smg_ank1_extra));
  printf("    Section magic: %08llX\n", ank1 -> ext -> magic);
  printf("    Section size (bytes): %llu\n", ank1 -> ext -> size);
  printf("    Bone animation data offset (hex): %08llX\n", ank1 -> ext -> bone_anim_data_offset);
  printf("    Scale array offset (hex): %08llX\n", ank1 -> ext -> scale_arr_offset);
  printf("    Rotation array offset (hex): %08llX\n", ank1 -> ext -> rot_arr_offset);
  printf("    Translation array offset (hex): %08llX\n", ank1 -> ext -> transl_arr_offset);
  printf("    Padding 1 size (bytes): %u\n", ank1 -> ext -> pad1_size);
  printf("    Padding 2 size (bytes): %u\n", ank1 -> ext -> pad2_size);
  printf("    Padding 3 size (bytes): %u\n", ank1 -> ext -> pad3_size);
  printf("    Padding 4 size (bytes): %u\n", ank1 -> ext -> pad4_size);
  printf("    Padding 5 size (bytes): %u\n", ank1 -> ext -> pad5_size);
  
  // done!
  end:
  return sizeof(owl_smg_ank1);
}

// comp
owl_char owl_comp_smg_ank1(owl_byte * ank11, owl_byte * ank12)
{
  return owl_comp_err;
}

// append the extra information of a ank1 section
owl_bool owl_get_smg_ank1_extra(owl_smg_ank1 * ank1)
{
  // check params
  owl_mem_space * sp = NULL;
  if (owl_check_smg_ank1_all(ank1, sizeof(owl_smg_ank1)) == owl_false
      || ank1 -> ext != NULL) return owl_false;
  
  // get it done
  sp = owl_create_mem_space(sizeof(owl_smg_ank1_extra));
  if (sp == NULL) goto err;
  ank1 -> ext = (void *) sp -> ptr;
  
  // magic
  ank1 -> ext -> magic = OWL_SMG_ANK1_MAGIC[0][0]; // magic (big endian)
  ank1 -> ext -> bone_anim_data_offset = OWL_SMG_ANK1_BONE_ANIM_DATA_OFFSET; // bone anim data offset
  ank1 -> ext -> pad1_size = OWL_SMG_ANK1_PAD1_SIZE; // pad1 size
  owl_umax tmp = OWL_SMG_ANK1_BONE_ANIM_DATA_OFFSET; // related to size
  tmp += ank1 -> main -> bone_count * OWL_SMG_ANK1_COMP_LENGTH * 6;
  tmp += (ank1 -> ext -> pad2_size = owl_get_padding_align_32_length(tmp)); // pad2 size
  ank1 -> ext -> scale_arr_offset = tmp; // scale array offset
  tmp += 4 * ank1 -> main -> scale_arr_length;
  tmp += (ank1 -> ext -> pad3_size = owl_get_padding_align_32_length(tmp)); // pad3 size
  ank1 -> ext -> rot_arr_offset = tmp; // rotation array offset
  tmp += 2 * ank1 -> main -> rot_arr_length;
  tmp += (ank1 -> ext -> pad4_size = owl_get_padding_align_32_length(tmp)); // pad4 size
  ank1 -> ext -> transl_arr_offset = tmp; // translation array offset
  tmp += 4 * ank1 -> main -> transl_arr_length;
  tmp += (ank1 -> ext -> pad5_size = owl_get_padding_align_32_length(tmp)); // pad5 size
  ank1 -> ext -> size = tmp; // size  
  
  // done!
  return owl_true;
  err:
  owl_free_mem_space(&((owl_mem_space) {(void *) ank1 -> ext, 1}));
  owl_free_mem_space(sp);
  return owl_false;
}

// get the byte size of an encoded ank1 structure
owl_umax owl_get_smg_ank1_bin_size(owl_smg_ank1 * ank1)
{
  // check params
  if (owl_check_smg_ank1_all((void *) ank1, sizeof(owl_smg_ank1)) == owl_false)
    return 0;
  // lol
  if (ank1 -> ext != NULL)
    return ank1 -> ext -> size;
  // calculate the size by getting the extra section
  if (owl_get_smg_ank1_extra(ank1) == owl_false)
    return 0;
  return ank1 -> ext -> size;
}

// get the error code of a ank1 string
owl_smg_ank1_err_cd owl_get_err_cd_smg_ank1(owl_str * raw, owl_endian endian)
{
  // reuse owl_create_smg_ank1()
  owl_smg_ank1 * tmp = owl_create_smg_ank1(raw, endian);
  owl_free_smg_ank1(tmp);
  return OWL_SMG_ANK1_ERR_CD;
}

// create a smg_ank1 structure from minimal arguments
owl_smg_ank1 * owl_get_smg_ank1_min_args(owl_byte loop_mode,
                                         owl_byte rot_lshift,
                                         owl_umax anim_length,
                                         owl_umax bone_count,
                                         owl_umax scale_arr_length,
                                         owl_umax rot_arr_length,
                                         owl_umax transl_arr_length,
                                         struct owl_smg_ank1_bone_anim_data ** bone_anim_data,
                                         owl_fmax * scale_arr,
                                         owl_smax * rot_arr,
                                         owl_fmax * transl_arr)
{
  // check params
  owl_mem_space * sp = NULL;
  owl_smg_ank1 * new = NULL;
  owl_smg_ank1_main test = {loop_mode, rot_lshift, anim_length, bone_count,
                            scale_arr_length, rot_arr_length, transl_arr_length,
                            bone_anim_data, scale_arr, rot_arr, transl_arr};
  if (owl_check_smg_ank1_main_all(&test, sizeof(owl_smg_ank1_main)) == owl_false)
    goto err;
  
  // allocate space
  sp = owl_create_mem_space(sizeof(owl_smg_ank1));
  if (sp == NULL) goto err;
  new = (void *) sp -> ptr; // structure
  sp = owl_create_mem_space(sizeof(owl_smg_ank1_main));
  if (sp == NULL) goto err;
  new -> main = (void *) sp -> ptr; // main
  sp = owl_create_mem_space(sizeof(struct owl_smg_ank1_bone_anim_data *) * bone_count);
  if (sp == NULL) goto err;
  new -> main -> bone_anim_data = (void *) sp -> ptr; // bone_anim_data *
  for (owl_umax i = 0; i < bone_count; i++) {
    // allocate space for each bone animation data struct
    sp = owl_create_mem_space(sizeof(struct owl_smg_ank1_bone_anim_data) * OWL_SMG_ANK1_COMP_LENGTH);
    if (sp == NULL) goto err;
    (new -> main -> bone_anim_data)[i] = (void *) sp -> ptr;
  }
  sp = owl_create_mem_space(sizeof(owl_fmax) * scale_arr_length);
  if (sp == NULL) goto err;
  new -> main -> scale_arr = (void *) sp -> ptr; // scale_arr
  sp = owl_create_mem_space(sizeof(owl_smax) * rot_arr_length);
  if (sp == NULL) goto err;
  new -> main -> rot_arr = (void *) sp -> ptr; // rot_arr
  sp = owl_create_mem_space(sizeof(owl_fmax) * transl_arr_length);
  if (sp == NULL) goto err;
  new -> main -> transl_arr = (void *) sp -> ptr; // transl_arr
  
  // data
  new -> main -> loop_mode = loop_mode;
  new -> main -> rot_lshift = rot_lshift;
  new -> main -> anim_length = anim_length;
  new -> main -> bone_count = bone_count;
  new -> main -> scale_arr_length = scale_arr_length;
  new -> main -> rot_arr_length = rot_arr_length;
  new -> main -> transl_arr_length = transl_arr_length;
  for (owl_umax i = 0; i < bone_count; i++)
    for (owl_umax j = 0; j < OWL_SMG_ANK1_COMP_LENGTH; j++) {
      (new -> main -> bone_anim_data)[i][j].kf_count = bone_anim_data[i][j].kf_count;
      (new -> main -> bone_anim_data)[i][j].data_index = bone_anim_data[i][j].data_index;
      (new -> main -> bone_anim_data)[i][j].interp_mode = bone_anim_data[i][j].interp_mode;
    }
  for (owl_umax i = 0; i < scale_arr_length; i++)
    (new -> main -> scale_arr)[i] = scale_arr[i];
  for (owl_umax i = 0; i < rot_arr_length; i++)
    (new -> main -> rot_arr)[i] = rot_arr[i];
  for (owl_umax i = 0; i < transl_arr_length; i++)
    (new -> main -> transl_arr)[i] = transl_arr[i];  
  
  // done!
  return new;
  err:
  if (new != NULL) {
    if (new -> main != NULL) {
      if (new -> main -> bone_anim_data != NULL) {
        for (owl_umax i = 0; i < new -> main -> bone_count; i++)
          owl_free_mem_space(&((owl_mem_space) {(void *) (new -> main -> bone_anim_data)[i], 1}));
        owl_free_mem_space(&((owl_mem_space) {(void *) new -> main -> bone_anim_data, 1}));
      }
      owl_free_mem_space(&((owl_mem_space) {(void *) new -> main -> scale_arr, 1}));
      owl_free_mem_space(&((owl_mem_space) {(void *) new -> main -> rot_arr, 1}));
      owl_free_mem_space(&((owl_mem_space) {(void *) new -> main -> transl_arr, 1}));
      owl_free_mem_space(&((owl_mem_space) {(void *) new -> main, 1}));
    }
    owl_free_mem_space(&((owl_mem_space) {(void *) new, 1}));
  }
  owl_free_mem_space(sp);
  return NULL;
}

// create a smg ank1 string
owl_str * owl_get_smg_ank1_as_str(owl_smg_ank1 * ank1, owl_endian endian)
{
  // check params
  owl_mem_space * sp = NULL;
  owl_str * new = NULL;
  if (owl_check_smg_ank1_all(ank1, sizeof(owl_smg_ank1)) == owl_false
      || owl_check_endian(endian) == owl_false) goto err;
  
  // create the extra section if not there
  if (ank1 -> ext == NULL && owl_get_smg_ank1_extra(ank1) == owl_false)
    goto err;
  
  // allocate space for the encoded ank1
  sp = owl_create_mem_space(ank1 -> ext -> size);
  if (sp == NULL) goto err;
  
  // write data
  owl_bitarr write = {&((owl_bytarr) {sp -> ptr, sp -> size}), 0, 0};
  
  // magic and size
  if (owl_write_std_uint32_mv(OWL_SMG_ANK1_MAGIC[0][0], &write, endian) == owl_false) goto err;
  if (owl_write_std_uint32_mv(ank1 -> ext -> size, &write, endian) == owl_false) goto err;  
  // loop_mode and rot_lshift
  if (owl_write_std_uint8_mv(ank1 -> main -> loop_mode, &write, endian) == owl_false) goto err;
  if (owl_write_std_uint8_mv(ank1 -> main -> rot_lshift, &write, endian) == owl_false) goto err;
  // anim_length, bone_count, scale_arr_length, rot_arr_length and transl_arr_length
  if (owl_write_std_uint16_mv(ank1 -> main -> anim_length, &write, endian) == owl_false) goto err;
  if (owl_write_std_uint16_mv(ank1 -> main -> bone_count, &write, endian) == owl_false) goto err;
  if (owl_write_std_uint16_mv(ank1 -> main -> scale_arr_length, &write, endian) == owl_false) goto err;
  if (owl_write_std_uint16_mv(ank1 -> main -> rot_arr_length, &write, endian) == owl_false) goto err;
  if (owl_write_std_uint16_mv(ank1 -> main -> transl_arr_length, &write, endian) == owl_false) goto err;
  // offsets
  if (owl_write_std_uint32_mv(ank1 -> ext -> bone_anim_data_offset, &write, endian) == owl_false) goto err;
  if (owl_write_std_uint32_mv(ank1 -> ext -> scale_arr_offset, &write, endian) == owl_false) goto err;
  if (owl_write_std_uint32_mv(ank1 -> ext -> rot_arr_offset, &write, endian) == owl_false) goto err;
  if (owl_write_std_uint32_mv(ank1 -> ext -> transl_arr_offset, &write, endian) == owl_false) goto err;
  // pad1
  if (ank1 -> ext -> pad1_size != 0)
    *(write.arr) = owl_copy_bytarr(&((owl_bytarr) {OWL_SMG_PAD_STR.arr -> ptr, ank1 -> ext -> pad1_size}), write.arr);
  // bone_anim_data
  for (owl_umax i = 0; i < ank1 -> main -> bone_count; i++)
    for (owl_umax j = 0; j < OWL_SMG_ANK1_COMP_LENGTH; j++) {
      // kf_count, data_index and interp_mode
      if (owl_write_std_uint16_mv((ank1 -> main -> bone_anim_data)[i][j].kf_count, &write, endian) == owl_false) goto err;
      if (owl_write_std_uint16_mv((ank1 -> main -> bone_anim_data)[i][j].data_index, &write, endian) == owl_false) goto err;    
      if (owl_write_std_uint16_mv((ank1 -> main -> bone_anim_data)[i][j].interp_mode, &write, endian) == owl_false) goto err;
    }
  // pad2
  if (ank1 -> ext -> pad2_size != 0)
    *(write.arr) = owl_copy_bytarr(&((owl_bytarr) {OWL_SMG_PAD_STR.arr -> ptr, ank1 -> ext -> pad2_size}), write.arr);
  // scale_arr
  for (owl_umax i = 0; i < ank1 -> main -> scale_arr_length; i++)
    if (owl_write_std_float32_mv((ank1 -> main -> scale_arr)[i], &write, endian) == owl_false) goto err;
  // pad3
  if (ank1 -> ext -> pad3_size != 0)
    *(write.arr) = owl_copy_bytarr(&((owl_bytarr) {OWL_SMG_PAD_STR.arr -> ptr, ank1 -> ext -> pad3_size}), write.arr);
  // rot_arr
  for (owl_umax i = 0; i < ank1 -> main -> rot_arr_length; i++)
    if (owl_write_std_sint16_mv((ank1 -> main -> rot_arr)[i], &write, endian) == owl_false) goto err;
  // pad4
  if (ank1 -> ext -> pad4_size != 0)
    *(write.arr) = owl_copy_bytarr(&((owl_bytarr) {OWL_SMG_PAD_STR.arr -> ptr, ank1 -> ext -> pad4_size}), write.arr);
  // transl_arr
  for (owl_umax i = 0; i < ank1 -> main -> transl_arr_length; i++)
    if (owl_write_std_float32_mv((ank1 -> main -> transl_arr)[i], &write, endian) == owl_false) goto err;
  // pad5
  if (ank1 -> ext -> pad3_size != 0)
    *(write.arr) = owl_copy_bytarr(&((owl_bytarr) {OWL_SMG_PAD_STR.arr -> ptr, ank1 -> ext -> pad5_size}), write.arr);
  
  // copy sp into new and return new
  new = owl_create_str(sp -> ptr, sp -> size, OWL_WCHAR_ENC_BIN);
  if (new == NULL) goto err;
  owl_free_mem_space(sp);
  
  // done!
  return new;
  err:
  owl_free_mem_space(sp);
  owl_free_str(new);
  return NULL;
}
